{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ic4_occAAiAT"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "ioaprt5q5US7"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "yCl0eTNH5RS3"
      },
      "outputs": [],
      "source": [
        "#@title MIT License\n",
        "#\n",
        "# Copyright (c) 2017 François Chollet\n",
        "#\n",
        "# Permission is hereby granted, free of charge, to any person obtaining a\n",
        "# copy of this software and associated documentation files (the \"Software\"),\n",
        "# to deal in the Software without restriction, including without limitation\n",
        "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n",
        "# and/or sell copies of the Software, and to permit persons to whom the\n",
        "# Software is furnished to do so, subject to the following conditions:\n",
        "#\n",
        "# The above copyright notice and this permission notice shall be included in\n",
        "# all copies or substantial portions of the Software.\n",
        "#\n",
        "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
        "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
        "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n",
        "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
        "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
        "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n",
        "# DEALINGS IN THE SOFTWARE."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ItXfxkxvosLH"
      },
      "source": [
        "# Classificazione di testo con TensorFlow Hub: Recensioni di film"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hKY4XMc9o8iB"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/text_classification_with_hub\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Visualizza su TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/it/tutorials/keras/text_classification_with_hub.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Esegui in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/it/tutorials/keras/text_classification_with_hub.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Visualizza il sorgente su GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/it/tutorials/keras/text_classification_with_hub.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Scarica il notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BYzaKBe8YXg0"
      },
      "source": [
        "Note: La nostra comunità di Tensorflow ha tradotto questi documenti. Poichè queste traduzioni sono *best-effort*, non è garantito che rispecchino in maniera precisa e aggiornata la [documentazione ufficiale in inglese](https://www.tensorflow.org/?hl=en). \n",
        "Se avete suggerimenti per migliorare questa traduzione, mandate per favore una pull request al repository Github [tensorflow/docs](https://github.com/tensorflow/docs). \n",
        "Per proporsi come volontari alla scrittura o alla review delle traduzioni della comunità contattate la \n",
        "[mailing list docs@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Eg62Pmz3o83v"
      },
      "source": [
        "Questo notebook classifica recensioni di film come *positive* o *negative* usando il testo delle revisioni. Questo è un esempio di classificazione *binaria*—o a due classi, un importante tipo di problema di machine learning largamente applicabile.\n",
        "\n",
        "Il tutorial dimostra l'applicazione di base del trasferimento di conoscenza (transfer learning n.d.t) con TensorFlow Hub e Keras.\n",
        "\n",
        "Useremo il [dataset IMDB](https://www.tensorflow.org/datasets/catalog/imdb_reviews) che contiene il testo di 50.000 recensioni di film dall'[Internet Movie Database](https://www.imdb.com/). Esse sono divise in 25,000 recensioni per l'addestramento e 25,000 revisioni per la verifica. Gli insiemi di addestramento e verifica sono *bilanciati*, nel senso che essi contengono un eguale numero di recensioni positive e negative.\n",
        "\n",
        "Questo notebook usa [tf.keras](https://www.tensorflow.org/guide/keras), un'API di alto livello per costruire ed addestrare modelli in TensorFlow, e [TensorFlow Hub](https://www.tensorflow.org/hub), una libreria ed una piattaforma per il trasferimento di conoscenza. Per un tutorial più avanzato di classificazione del testo che usa `tf.keras`, vedere la [MLCC Text Classification Guide](https://developers.google.com/machine-learning/guides/text-classification/)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2ew7HTbPpCJH"
      },
      "outputs": [],
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "import numpy as np\n",
        "\n",
        "try:\n",
        "  # %tensorflow_version only exists in Colab.\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "  pass\n",
        "import tensorflow as tf\n",
        "\n",
        "!pip install tensorflow-hub\n",
        "!pip install tfds-nightly\n",
        "import tensorflow_hub as hub\n",
        "import tensorflow_datasets as tfds\n",
        "\n",
        "print(\"Version: \", tf.__version__)\n",
        "print(\"Eager mode: \", tf.executing_eagerly())\n",
        "print(\"Hub version: \", hub.__version__)\n",
        "print(\"GPU is\", \"available\" if tf.config.experimental.list_physical_devices(\"GPU\") else \"NOT AVAILABLE\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iAsKG535pHep"
      },
      "source": [
        "## Scarichiamo il dataset IMDB\n",
        "\n",
        "Il dataset IMDB è disponibile su [imdb reviews](https://www.tensorflow.org/datasets/catalog/imdb_reviews) o su [TensorFlow datasets](https://www.tensorflow.org/datasets). Il codice seguente scarica il dataset IMDB sulla vostra macchina (o eseguibile colab):"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zXXx5Oc3pOmN"
      },
      "outputs": [],
      "source": [
        "# Split the training set into 60% and 40%, so we'll end up with 15,000 examples\n",
        "# for training, 10,000 examples for validation and 25,000 examples for testing.\n",
        "train_data, validation_data, test_data = tfds.load(\n",
        "    name=\"imdb_reviews\", \n",
        "    split=('train[:60%]', 'train[60%:]', 'test'),\n",
        "    as_supervised=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l50X3GfjpU4r"
      },
      "source": [
        "## Esploriamo i dati\n",
        "\n",
        "Prendiamoci un momento per capire la struttura dei dati. Ogni esempio è una frase che rappresenta la recensione di un film e l'etichetta corrispondente. La frase non è pre-elaborata in alcun modo. L'etichetta è un valore intero tra 0 e 1, ove 0 è una recensione negativa, ed 1 è una recensione positiva.\n",
        "\n",
        "Stampiamo i primi 10 esempi."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "QtTS4kpEpjbi"
      },
      "outputs": [],
      "source": [
        "train_examples_batch, train_labels_batch = next(iter(train_data.batch(10)))\n",
        "train_examples_batch"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IFtaCHTdc-GY"
      },
      "source": [
        "E stampiamo anche le prime 10 etichette."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tvAjVXOWc6Mj"
      },
      "outputs": [],
      "source": [
        "train_labels_batch"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LLC02j2g-llC"
      },
      "source": [
        "## Costruiamo il modello\n",
        "\n",
        "La rete neurale viene creata impilando livelli—ciò richiede tre decisioni architetturali principali:\n",
        "\n",
        "* Come rappresentare il testo?\n",
        "* Quanti livelli usare nel modello?\n",
        "* Quante *unità nascoste* usare per ogni livello?\n",
        "\n",
        "In questo esempio, i dati di input sono frasi. Le etichette da predire sono 0 o 1.\n",
        "\n",
        "Un modo di rappresentare il testo è convertire le frasi in vettori di assorbimento (embedding n.d.t.). Possiamo usare un (livello n.d.t) di assorbimento del testo pre-addestrato come primo livello, ed avremo tre vantaggi:\n",
        "\n",
        "*   non dovremo preoccuparci della pre-elaborazione del testo,\n",
        "*   potremo beneficiare del trasferimento di conoscenza,\n",
        "*   il risultato dell'assorbimento ha una lunghezza fissa, e quindi sarà più semplice da elaborare.\n",
        "\n",
        "Per questo esempio useremo un **modello di assorbimento pre-addestrato** preso da [TensorFlow Hub](https://www.tensorflow.org/hub) e chiamato [google/tf2-preview/gnews-swivel-20dim/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1).\n",
        "\n",
        "Qui ci sono altri tre modelli pre-addestrati, da provare, che rendono ancora più interessante questo tutorial:\n",
        "\n",
        "* [google/tf2-preview/gnews-swivel-20dim-with-oov/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim-with-oov/1) - lo stesso di [google/tf2-preview/gnews-swivel-20dim/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1), ma con il 2.5% del vocabolario convertito in OOV buckets. Ciò può essere d'aiuto se il vocabolario del nostro caso e il vocabolario del modello non coincidono completamente.\n",
        "* [google/tf2-preview/nnlm-en-dim50/1](https://tfhub.dev/google/tf2-preview/nnlm-en-dim50/1) - Un modello più ampio con un vocabolario da ~1M di vocaboli e 50 dimensioni.\n",
        "* [google/tf2-preview/nnlm-en-dim128/1](https://tfhub.dev/google/tf2-preview/nnlm-en-dim128/1) - Un modello ancora più ampio con un vocabolario da ~1M di vocaboli e 128 dimensioni."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "In2nDpTLkgKa"
      },
      "source": [
        "Per prima cosa creiamo un livello Keras che usa un modello TensorFlow Hub per eseguire l'assorbimento (embedding n.d.t) delle frasi, e proviamolo su una coppia di esempi di input. Notate che, indipendentemente dalla lunghezza del testo di input, il formato dell'output dell'assorbimento è: `(num_examples, embedding_dimension)`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_NUbzVeYkgcO"
      },
      "outputs": [],
      "source": [
        "embedding = \"https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1\"\n",
        "hub_layer = hub.KerasLayer(embedding, input_shape=[], \n",
        "                           dtype=tf.string, trainable=True)\n",
        "hub_layer(train_examples_batch[:3])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dfSbV6igl1EH"
      },
      "source": [
        "Ora costruiamo il modello completo:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xpKOoWgu-llD"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.Sequential()\n",
        "model.add(hub_layer)\n",
        "model.add(tf.keras.layers.Dense(16, activation='relu'))\n",
        "model.add(tf.keras.layers.Dense(1))\n",
        "\n",
        "model.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6PbKQ6mucuKL"
      },
      "source": [
        "I livelli sono impilati sequenzialmente per realizzare il classificatore:\n",
        "\n",
        "1. Il primo livello è un livello TensorFlow Hub. Questo livello usa un modello Saved Model pre-addestrato per mappare una frase nel suo vettore di assorbimento. Il modello di assorbimento del testo pre-addestrato che useremo ([google/tf2-preview/gnews-swivel-20dim/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1)) divide le frasi in token, assorbe ciascun token e poi combina gli assorbimenti. Le dimensioni risultanti sono: `(num_examples, embedding_dimension)`.\n",
        "2. Questo vettore di output di lunghezza fissa è passato attraverso un livello completamente connesso (`Denso`) con 16 unità nascoste.\n",
        "3. L'ultimo livello è connesso densamente con un singolo nodo di output. Usando la funzione di attivazione `sigmoid`, questo valore è un float tra 0 e 1, che rappresenta una probabilità, o un livello di confidenza.\n",
        "\n",
        "Compiliamo il modello."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "L4EqVWg4-llM"
      },
      "source": [
        "### Funzione obiettivo e ottimizzatore\n",
        "\n",
        "Un modello, per l'addestramento, ha bisogno di una funzione obiettivo e di un ottimizzatore. Essendo questo un problema di classificazione binaria e l'output del modello una probabilità (un livello a unità singola con un'attivazione sigmoid), useremo la funzione obiettivo `binary_crossentropy`.\n",
        "\n",
        "Questa non è l'unica scelta possibile per una funzione obiettivo, potreste, per esempio, scegliere la `mean_squared_error`. In generale, però, `binary_crossentropy` è migliore per gestire probabilità—essa misura la \"distanza\" tra distribuzioni di probabilità o, nel nostro caso, tra la distribuzione dei dati reali e le previsioni.\n",
        "\n",
        "Nel seguito, quando esploreremo i problemi di regressione (diciamo, per prevedere il prezzo di una casa), vedremo come usare un'altra funzione obiettivo chiamata scarto quadratico medio.\n",
        "\n",
        "Adesso, configuriamo il modello per usare un ottimizzatore ed una funzione obiettivo:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Mr0GP-cQ-llN"
      },
      "outputs": [],
      "source": [
        "model.compile(optimizer='adam',\n",
        "              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),\n",
        "              metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "35jv_fzP-llU"
      },
      "source": [
        "## Addestriamo il modello\n",
        "\n",
        "Addestriamo il modello per 20 epoche in mini-lotti di 512 campioni l'uno. Cioè 20 iterazioni su tutti i campioni nei tensori `x_train` e `y_train`. Durante l'addestramento, controlliamo l'obiettivo e l'accuratezza del modello sui 10.000 campioni dell'insieme di validazione:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tXSGrjWZ-llW"
      },
      "outputs": [],
      "source": [
        "history = model.fit(train_data.shuffle(10000).batch(512),\n",
        "                    epochs=20,\n",
        "                    validation_data=validation_data.batch(512),\n",
        "                    verbose=1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9EEGuDVuzb5r"
      },
      "source": [
        "## Valutiamo il modello\n",
        "\n",
        "E andiamo a vedere come si comporta il modello. Saranno restituiti due valori. Obietttivo (un numero che rappresenta il nostro errore, per cui valori piccoli sono migliori), e accuratezza."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zOMKywn4zReN"
      },
      "outputs": [],
      "source": [
        "results = model.evaluate(test_data.batch(512), verbose=2)\n",
        "\n",
        "for name, value in zip(model.metrics_names, results):\n",
        "  print(\"%s: %.3f\" % (name, value))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z1iEXVTR0Z2t"
      },
      "source": [
        "Questo approccio abbastanza ingenuo raggiunge un'accuratezza di circa l'87%. Con approcci più avanzati, il modello potrebbe avvicinarsi al 95%."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5KggXVeL-llZ"
      },
      "source": [
        "## Ulteriori letture\n",
        "\n",
        "Per un metodo più generale di trattamento degli input stringa e per un'analisi più dettagliata del progresso di accuratezza e obiettivo durante l'addestramento, date un'occhiata [qui](https://www.tensorflow.org/tutorials/keras/basic_text_classification)."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "text_classification_with_hub.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
